package com.fgs.common.api;

import android.app.Application;
import android.text.TextUtils;

import com.fgs.common.manager.CommonSharedPreferenceManager;
import com.fgs.common.utils.CommonUtil;
import com.fgs.common.utils.LogUtil;
import com.fgs.common.utils.NetWorkUtil;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

/**
 * @author fgs
 * @date 2020/10/9
 * @description
 **/
public class CommonConfigTwo {

    //读超时长，单位：毫秒
    public static final int READ_TIME_OUT = 60000;
    //连接时长，单位：毫秒
    public static final int CONNECT_TIME_OUT = 60000;
    private Retrofit mRetrofit;
    private static volatile CommonConfigTwo commonConfig;
    private CommonOptions commonOptions;

    public static CommonConfigTwo getInstance() {
        if (commonConfig == null) {
            synchronized (CommonConfigTwo.class) {
                if (commonConfig == null) {
                    commonConfig = new CommonConfigTwo();
                }
            }
        }
        return commonConfig;
    }

    private CommonConfigTwo() {
    }

    public void init(Application application, ICommonConfig iCommonConfig) {
        CommonUtil.init(application);
        this.commonOptions = iCommonConfig.configOptions();
        initRetrofit(iCommonConfig);
    }

    private void initRetrofit(ICommonConfig iCommonConfig) {
        String phoneInfo = CommonSharedPreferenceManager.getInstance().getPhoneInfo();

        HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor();
        logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        //缓存
        File cacheFile = new File(CommonUtil.getContext().getCacheDir(), "cache");
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); //100Mb
        //增加头部信息
        Interceptor headerInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                LogUtil.print("CommonConfig----requestUrl", chain.request().url().toString());
                String terminal = "android(" + phoneInfo + ")";
                String appId = "2237102865";
                String secret = "YgAqeZq1eM#6#xRXkjtDTD%Ol4oxzBIlYI#k75HJml4bCr!F8YTqySDueKRY%1GB";

                Map<String, String> params = new HashMap<>();
                String method = chain.request().method();
                if (method.equals("GET")) {
                    Set<?> pNames = chain.request().url().queryParameterNames();
                    Iterator<?> iterator = pNames.iterator();
                    while (iterator.hasNext()) {
                        String pName = (String) iterator.next();
                        String pValue = chain.request().url().queryParameter(pName);
                        params.put(pName, pValue);
                    }
                } else if (method.equals("POST")) {
                    if (isNotNeedAddRequestLength(chain.request().url().toString())) {
                        params.put("length", "0");
                    } else {
                        String bodyInfo = chain.request().body().contentLength() + "";
                        params.put("length", bodyInfo);
                    }

                }
                params.put("terminal", terminal);
                params.put("appid", appId);
                Request build = chain.request().newBuilder()
                        .addHeader("terminal", terminal)
                        .addHeader("appid", appId)
                        .addHeader("signature", GetSignUtil.getSign(params, secret))
                        .addHeader("Content-Type", "application/json;")//设置允许请求json数据
                        .build();


                return chain.proceed(build);
            }
        };


        //创建一个OkHttpClient并设置超时时间
        OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder()
                .readTimeout(READ_TIME_OUT, TimeUnit.MILLISECONDS)
                .connectTimeout(CONNECT_TIME_OUT, TimeUnit.MILLISECONDS)
                .addInterceptor(mRewriteCacheControlInterceptor)//没网的情况下
                .addNetworkInterceptor(mRewriteCacheControlInterceptor)//有网的情况下
//                .addNetworkInterceptor(new TokenHeaderInterceptor())
                .addInterceptor(headerInterceptor)
                .addInterceptor(logInterceptor)
                .cache(cache);

        OkHttpClient client = iCommonConfig.okHttpClient(okHttpClientBuilder).build();


        Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
                .client(client)
                .baseUrl(commonOptions.getBaseUrl())
                .addConverterFactory(ScalarsConverterFactory.create())//请求结果转换为基本类型，一般为String
                .addConverterFactory(GsonConverterFactory.create())//请求的结果转为实体类
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create());

        Retrofit retrofit = iCommonConfig.retrofit(retrofitBuilder).build();
        mRetrofit = retrofit;
    }

    //上传图片接口length传0
    private boolean isNotNeedAddRequestLength(String url) {
        if (TextUtils.isEmpty(url)) return false;
        return url.contains("picture");
    }

    /**
     * 设缓存有效期为两天
     */
    private static final long CACHE_STALE_SEC = 60 * 60 * 24 * 2;

    /**
     * 云端响应头拦截器，用来配置缓存策略
     * Dangerous interceptor that rewrites the server's cache-control header.
     */
    private final Interceptor mRewriteCacheControlInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();//拦截器获取请求
            String cacheControl = request.cacheControl().toString();//服务器的缓存策略
            if (!NetWorkUtil.isNetConnected(CommonUtil.getContext())) {//断网时配置缓存策略
                request = request.newBuilder()
                        .cacheControl(TextUtils.isEmpty(cacheControl) ?
                                CacheControl.FORCE_NETWORK : CacheControl.FORCE_CACHE)
//                        .cacheControl(CacheControl.FORCE_CACHE)
                        .build();
            }
            Response originalResponse = chain.proceed(request);
            if (NetWorkUtil.isNetConnected(CommonUtil.getContext())) {//在线缓存
//                KLog.e("在线缓存2分钟");
                return originalResponse.newBuilder()
                        .removeHeader("Pragma")
                        .header("Cache-Control", cacheControl)//应用服务端配置的缓存策略
//                        .header("Cache-Control", "public, max-age=" + 60 * 2)//有网的时候连接服务器请求,缓存(时间)
                        .build();
            } else {//离线缓存
                /**
                 * only-if-cached:(仅为请求标头)
                 *　 请求:告知缓存者,我希望内容来自缓存，我并不关心被缓存响应,是否是新鲜的.
                 * max-stale:
                 *　 请求:意思是,我允许缓存者，发送一个,过期不超过指定秒数的,陈旧的缓存.
                 *　 响应:同上.
                 * max-age:
                 *   请求:强制响应缓存者，根据该值,校验新鲜性.即与自身的Age值,与请求时间做比较.如果超出max-age值,
                 *   则强制去服务器端验证.以确保返回一个新鲜的响应.
                 *   响应:同上.
                 */
                //需要服务端配合处理缓存请求头，不然会抛出： HTTP 504 Unsatisfiable Request (only-if-cached)
//                KLog.e("离线缓存"+CACHE_STALE_SEC+"秒");
                return originalResponse.newBuilder()
                        .removeHeader("Pragma")
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + CACHE_STALE_SEC)//CACHE_STALE_SEC
                        .build();
            }
        }
    };


    /**
     * 创建API
     */
    public <T> T create(Class<T> clazz) {
        return mRetrofit.create(clazz);
    }

    public CommonOptions commonOptions() {
        return commonOptions;
    }
}
